package com.tanx.cqrs.infrastructure.spring.command.handler;

import com.tanx.cqrs.aggregate.Aggregate;
import com.tanx.cqrs.command.Command;
import com.tanx.cqrs.command.TargetAggregateIdentifier;
import com.tanx.cqrs.command.handler.CommandMeta;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.Collection;

/**
 * 命令元数据工厂
 */
@Slf4j
public class CommandMetaFactory {
    public static Collection<CommandMeta> create(SpringBeanCommandHandlerInstance instance) {
        Collection<CommandMeta> commandMetas = new ArrayList<>();
        if (instance.isAggregate()) {
            addAggregate(instance, commandMetas);
        } else {
            addService(instance, commandMetas);
        }

        return commandMetas;
    }

    /**
     * 1,从方法的参数列表中获取参数
     * 2,根据参数查找对应的字段
     */
    private static void addService(SpringBeanCommandHandlerInstance instance, Collection<CommandMeta> commandMetas) {
        CommandMeta meta;
        Parameter[] parameters = instance.getMethod().getParameters();
        for (Parameter parameter : parameters) {
            Class<?> type = parameter.getType();
            if (Command.class.isAssignableFrom(type)) {
                continue;
            }
            if (type.getAnnotation(Aggregate.class) == null) {
                throw new RuntimeException("参数:" + type + "必须为聚合");
            }
            meta = new CommandMeta(type);
            TargetAggregateIdentifier annotation = parameter.getAnnotation(TargetAggregateIdentifier.class);
            if (annotation == null) {
                continue;
            }
            meta.setIdentifier(annotation);
            meta.setFieldName(annotation.value());
            try {
                Field field = instance.getCommandClass().getField(annotation.value());
                meta.setField(field);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            }
            commandMetas.add(meta);
        }
    }

    /**
     * 1,从字段中取得唯一的一个注解
     * 2,获取字段名称
     * 3,获取字段
     */
    private static void addAggregate(SpringBeanCommandHandlerInstance instance, Collection<CommandMeta> commandMetas) {
        CommandMeta commandMeta = new CommandMeta(instance.getBean().getClass());
        //TODO:获取类中的所有字段
        Field[] fields = instance.getCommandClass().getDeclaredFields();
        for (Field field : fields) {
            TargetAggregateIdentifier annotation = field.getAnnotation(TargetAggregateIdentifier.class);
            if (annotation != null) {
                commandMeta.setField(field);
                commandMeta.setFieldName(field.getName());
                commandMeta.setIdentifier(annotation);
            }
        }
        commandMetas.add(commandMeta);
    }
}
